package com.bruce.nettyDemo.http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * Created by bruce on 19/3/30 -- 9:52
 * 自定义的助手类
 */
public class HttpHandler extends SimpleChannelInboundHandler<HttpObject> {
    /**
     * 生命周期:  curl localhost:8888
     * telnet localhost 8888
     *>>>
     * 助手类添加
     * channel注册
     * channel活跃
     * /0:0:0:0:0:0:0:1:50519
     * channel数据读取完毕
     * channel数据读取完毕
     * channel不活跃
     * channel移除
     * 助手类移除
     */
    /**
     * 读取客户端发送来的消息
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx,
                                HttpObject msg) throws Exception {
        if (msg instanceof HttpRequest) {
            dealHttpRequest(ctx, msg);
        }
    }

    //channel活跃
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel活跃");
        super.channelActive(ctx);
    }

    //不活跃
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel不活跃");
        super.channelInactive(ctx);
    }

    //channel数据读取完毕就会触发这个事件
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel数据读取完毕");
        super.channelReadComplete(ctx);
    }

    //channel注册
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel注册");
        super.channelRegistered(ctx);
    }

    //channel移除
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channel移除");
        super.channelUnregistered(ctx);
    }

    //channel可写事件被更改
    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        System.out.println("助手类移除");
        super.channelWritabilityChanged(ctx);
    }

    //channel发生了异常，需要关闭
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("channel发生了异常");
        super.exceptionCaught(ctx, cause);
    }

    //用户事件的触发
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        System.out.println("助手类移除");
        super.userEventTriggered(ctx, evt);
    }

    //助手类添加
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("助手类添加");
        super.handlerAdded(ctx);
    }

    //助手类移除
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("助手类移除");
        super.handlerRemoved(ctx);
    }

    /**
     * 专门处理http请求
     *
     * @param ctx channel的持有上下文对象
     * @param msg 客户端发送来的消息
     */
    private void dealHttpRequest(ChannelHandlerContext ctx, HttpObject msg) {
        //获取到channel
        Channel channel = ctx.channel();
        //显示客户端的远程地址
        System.out.println(channel.remoteAddress());
        //定义发送给客户端的消息
        ByteBuf content = Unpooled.copiedBuffer("hello netty", CharsetUtil.UTF_8);
        /**
         * 构建一个相应客户端的http response
         */
        HttpVersion httpVersion = HttpVersion.HTTP_1_1;
        HttpResponseStatus responseStatus = HttpResponseStatus.OK;
        //设置版本、响应码和内容
        FullHttpResponse response = new DefaultFullHttpResponse(httpVersion, responseStatus, content);
        /**
         * 响应头
         */
        HttpHeaders headers = response.headers();
        headers.set(HttpHeaderNames.CONTENT_TYPE, "text/plain");//响应的数据类型
        headers.set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());//响应的数据的长度
        /**
         * 发送消息给客户端,把消息刷到客户端去
         */
        ctx.writeAndFlush(response);
    }
}
